﻿using Common.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using TSharp.Core.Env;
using TSharp.Core.Mvc;
using TSharp.Core.Mvc.Properties;
using TSharp.Core.Osgi;

[assembly: RegExtensionPoint(typeof(CollectControllerManage))]
namespace TSharp.Core.Mvc
{
    /// <summary>
    ///     Action功能收集类
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public sealed class ActionRightAttribute : Attribute
    {
        public ActionRightAttribute(string title)
        {
            Title = title;
        }

        /// <summary>
        ///     Action功能描述
        /// </summary>
        public string Title { get; private set; }
    }

    /// <summary>
    ///     Action权限验证标识类
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public sealed class ActionRightToAttribute : Attribute
    {
        public ActionRightToAttribute(Type controllerType, string actionName)
        {
            ControllerType = controllerType;
            ActionName = actionName;
        }

        public ActionRightToAttribute(string actionName)
        {
            ActionName = actionName;
        }

        /// <summary>
        ///     Controller类型
        /// </summary>
        public Type ControllerType { get; private set; }

        /// <summary>
        ///     Action的名称
        /// </summary>
        public string ActionName { get; private set; }
    }

    /// <summary>
    ///     Controller收集类
    /// </summary>
    public class RegCollectControllerAttribute : RegExtensionAttribute
    {
        public RegCollectControllerAttribute(string groupName, Type controllerType)
        {
            ControllerType = controllerType;
            GroupName = groupName;
        }

        /// <summary>
        ///     Controller描述
        /// </summary>
        public string GroupName { get; private set; }

        /// <summary>
        ///     Controller类型
        /// </summary>
        public Type ControllerType { get; private set; }
    }


    /// <summary>
    ///     资源类别注册类
    /// </summary>
    public class CollectControllerManage : ExtensionPoint<RegCollectControllerAttribute>
    {
        private static readonly List<RegCollectControllerAttribute> controllers =
            new List<RegCollectControllerAttribute>();

        public static IFunctionality Functionality
        {
            get { return LazyLoading.New<IFunctionality>(); }
        }

        /// <summary>
        ///     注册Controller，OSGI实现
        /// </summary>
        protected override void Register(Assembly assembly, RegCollectControllerAttribute attribute)
        {
            controllers.Add(attribute);
        }

        /// <summary>
        ///     注销Controller
        /// </summary>
        protected override void UnRegister(Assembly assembly, RegCollectControllerAttribute attribute)
        {
            controllers.Remove(attribute);
        }

        public static void ProcessActionsIntoDatabase()
        {
            if (controllers.Count == 0)
                return;
            lock (controllers)
            {
                if (controllers.Count == 0)
                    return;

                try
                {
                    var list = new List<ControllerFunc>();
                    foreach (RegCollectControllerAttribute item in controllers)
                    {
                        //Controller
                        ControllerFunc ctrFunc = list.FirstOrDefault(p => p.Title == item.GroupName && p.Code == null);
                        var cf = new ControllerFunc();
                        if (ctrFunc == null) //如果Controller不存在，则添加
                        {
                            cf.Id = Guid.NewGuid();
                            cf.Title = item.GroupName;
                            list.Add(cf);
                        }

                        //Action
                        IEnumerable<MethodInfo> actions =
                            item.ControllerType.GetMethods()
                                .Where(x => typeof(ActionResult).IsAssignableFrom(x.ReturnType) &&
                                            x.IsDefined(typeof(ActionRightAttribute), false));
                        list.AddRange(from ac in actions
                                      let actionNameAttr =
                                          ac.GetCustomAttributes(typeof(ActionRightAttribute), false).FirstOrDefault()
                                          as
                                          ActionRightAttribute
                                      let title = actionNameAttr.Title
                                      select new ControllerFunc
                                          {
                                              Id = Guid.NewGuid(),
                                              ParentId = ctrFunc == null ? cf.Id : ctrFunc.Id,

                                              //Code = ac.DeclaringType.Namespace + "/" + ac.DeclaringType.Name + "/" + ac.Name,
                                              Code =
                                                  GetActionUrl(ac.DeclaringType.Namespace, ac.DeclaringType.Name,
                                                               ac.Name),
                                              Title = title
                                          });
                    }
                    controllers.Clear();

                    Functionality.Update(list);
                }
                catch (Exception e)
                {
                    log.Error("收集action时发生错误！" + e.Message, e);
                }
            }
        }
        private static ILog log = LogManager.GetLogger<CollectControllerManage>();
        public static string GetActionUrl(string @namespace, string controllerName, string actionName)
        {
            var rvd = new RouteValueDictionary();
            string[] temp = @namespace.Split('.').ToArray();
            for (int i = 0; i < temp.Length; i++)
            {
                if (StringComparer.OrdinalIgnoreCase.Compare(temp[i], "Areas") == 0)
                {
                    if ((i + 1) < temp.Length)
                    {
                        rvd.Add("Area", temp[i + 1]);
                        break;
                    }
                }
            }
            if (!controllerName.EndsWith("Controller", StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException(MvcResources.ControllerExtensions_TargetMustEndInController, "action");
            }
            controllerName = controllerName.Substring(0, controllerName.Length - "Controller".Length);
            if (controllerName.Length == 0)
            {
                throw new ArgumentException(MvcResources.ControllerExtensions_CannotRouteToController, "action");
            }
            return StrRoute((string)rvd["Area"], controllerName, actionName);
        }

        public static string StrRoute(string area, string control, string action)
        {
            return string.Format("/{0}/{1}/{2}", area, control, action);
        }
    }

    /// <summary>
    ///     Controller和Action信息类
    /// </summary>
    public class ControllerFunc
    {
        public Guid Id { get; set; }

        public Guid? ParentId { get; set; }

        public string Code { get; set; }

        public string Title { get; set; }
    }
}